package com.tdk.wifidirectserver.ui.main

import android.net.wifi.p2p.WifiP2pConfig
import android.net.wifi.p2p.WifiP2pDevice
import android.net.wifi.p2p.WifiP2pGroup
import android.net.wifi.p2p.WifiP2pInfo
import android.net.wifi.p2p.WifiP2pManager
import android.net.wifi.p2p.WifiP2pManager.ActionListener
import android.os.Build
import android.text.TextUtils
import android.util.Log
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.tdk.wifidirectserver.inter.WifiDirectActionListener
import com.tdk.wifidirectserver.util.mConnectivityUtil

class MainViewModel : ViewModel() {
    private val mTAG: String = "MainViewModel"

    //扫描状态
    var isScanning: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)

    //本机p2p设备信息
    var localWifiP2pDevice: MutableLiveData<WifiP2pDevice?> = MutableLiveData<WifiP2pDevice?>(null)

    // 扫描到的p2p设备列表
    var scanWifiP2pDeviceList: MutableLiveData<MutableList<WifiP2pDevice>> = MutableLiveData(mutableListOf())

    // 已经连接的p2p设备列表
    var connectedWifiP2pDeviceList: MutableLiveData<MutableList<WifiP2pDevice>> = MutableLiveData(mutableListOf())

    //连接状态
    var isConnected: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)

    //连接的设备信息
    var connectedWifiP2pDevice: MutableLiveData<WifiP2pInfo?> = MutableLiveData<WifiP2pInfo?>(null)


    //连接的IP信息
    var connectedWifiP2pInfo: MutableLiveData<String> = MutableLiveData<String>()

    var connectedWifiP2pGroup: MutableLiveData<WifiP2pGroup?> = MutableLiveData<WifiP2pGroup?>()
    //监听2个数据livedata

    val mediatorLiveData: MediatorLiveData<Pair<Boolean, WifiP2pInfo?>> =
        MediatorLiveData<Pair<Boolean, WifiP2pInfo?>>()

    init {
        mediatorLiveData.addSource(isConnected) {
            mediatorLiveData.value = Pair(it, connectedWifiP2pDevice.value)
        }
        mediatorLiveData.addSource(connectedWifiP2pDevice) {
            mediatorLiveData.value = Pair(isConnected.value!!, it)
        }
    }


    //开始扫描
    fun startScan() {
        mConnectivityUtil.discoverPeers(object : ActionListener {
            override fun onSuccess() {
                Log.d(mTAG, "startScan: onSuccess")
                isScanning.postValue(true)
            }

            override fun onFailure(p0: Int) {
                Log.d(mTAG, "startScan: onFailure $p0")
            }

        })
    }

    //停止扫描
    fun stopScan() {
        mConnectivityUtil.stopPeerDiscovery(object : ActionListener {
            override fun onSuccess() {
                Log.d(mTAG, "stopScan: onSuccess")
                isScanning.postValue(false)
            }

            override fun onFailure(p0: Int) {
                Log.d(mTAG, "stopScan: onFailure $p0")
            }
        })
    }

    fun initConfig() {
        Log.d(mTAG, "initConfig: ")
        mConnectivityUtil.initConfig(object : WifiDirectActionListener {
            override fun wifiP2pEnabled(enabled: Boolean) {
                Log.d(mTAG, "wifiP2pEnabled: $enabled")

            }

            override fun onConnectionInfoAvailable(wifiP2pInfo: WifiP2pInfo?) {
                Log.d(
                    mTAG,
                    "onConnectionInfoAvailable: $wifiP2pInfo" + "---isOwner==" + wifiP2pInfo?.isGroupOwner + "---isFormed==" + wifiP2pInfo?.groupFormed
                )
                wifiP2pInfo?.let {
                    if (it.groupFormed && !it.isGroupOwner) {
                        isConnected.postValue(true)
                        val ip = it.groupOwnerAddress.hostAddress
                        if (!TextUtils.isEmpty(ip)) {
                            Log.d(mTAG, "onConnectionInfoAvailable: ip==$ip")
                            connectedWifiP2pInfo.postValue(ip)
                        }
                        connectedWifiP2pDevice.postValue(it)
                    }

                    if (it.groupFormed && it.isGroupOwner) {
                        connectedWifiP2pDevice.postValue(it)
                    }
                }
            }

            override fun onDisconnection() {
                Log.d(mTAG, "onDisconnection")
            }

            override fun onSelfDeviceAvailable(wifiP2pDevice: WifiP2pDevice?) {
                Log.d(mTAG, "onSelfDeviceAvailable: $wifiP2pDevice")
                //创建群组之后
                if (wifiP2pDevice != null && connectedWifiP2pDevice.value != null) {
                    Log.d(mTAG, "wifiP2pDevice.isGroupOwner:${wifiP2pDevice.isGroupOwner}")
                    if (wifiP2pDevice.status == WifiP2pDevice.CONNECTED && !connectedWifiP2pDevice.value!!.isGroupOwner) {
                        Log.d(mTAG, "onSelfDeviceAvailable: 连接成功")

                        isConnected.postValue(true)
                    } else {
                        Log.d(mTAG, "onSelfDeviceAvailable: 连接失败")
                        isConnected.postValue(false)
                    }
                    localWifiP2pDevice.postValue(wifiP2pDevice)
                } else {
                    localWifiP2pDevice.postValue(null)
                }

            }

            override fun onPeersAvailable(wifiP2pDeviceList: Collection<WifiP2pDevice?>?) {
                Log.d(mTAG, "onPeersAvailable: $wifiP2pDeviceList")
//                    val list: MutableList<WifiP2pDevice> = scanWifiP2pDeviceList.value!!
//                    wifiP2pDeviceList?.forEach {
//                        if (!list.contains(it)) {
//                            list.add(it!!)
//                        }
//                    }
                val list: MutableList<WifiP2pDevice> = mutableListOf()

                wifiP2pDeviceList?.let { it ->
                    it.forEach {
                        it?.let {
                            if (!list.contains(it)) {
                                list.add(it)
                            }
                        }
                    }
                    scanWifiP2pDeviceList.postValue(list)
//                        if (it.status == WifiP2pDevice.CONNECTED) {
//                            if (!connectedWifiP2pDeviceList.value?.contains(it)!!) {
//                                connectedWifiP2pDeviceList.value?.add(it)
//                            }
//                        }
                }
                val connectedList = connectedWifiP2pDeviceList.value!!
                val iterator = connectedList.iterator()
                while (iterator.hasNext()) {
                    val it = iterator.next()
                    val item =
                        list.find { wifiP2pDevice -> wifiP2pDevice.deviceAddress == it.deviceAddress && it.status != WifiP2pDevice.CONNECTED }
                    if (item == null) {
                        connectedList.remove(it)
                    }
                }

                list.forEach {
                    if (it.status == WifiP2pDevice.CONNECTED) {
                        val item =
                            connectedList.find { wifiP2pDevice -> wifiP2pDevice.deviceAddress == it.deviceAddress }
                        if (item == null) {
                            connectedList.add(it)
                        }
                    }
                }

                if (connectedList.size > 0) {
                    Log.d(mTAG, "connectedList: ${connectedList.size}")
                    isConnected.postValue(true)
                } else {
                    Log.d(mTAG, "connectedList is empty")
                    isConnected.postValue(false)
                }
                Log.d(mTAG, "connectedList: $connectedList")
                connectedWifiP2pDeviceList.postValue(connectedList)
            }

            override fun onChannelDisconnected() {
                Log.d(mTAG, "onChannelDisconnected")
            }
        })
    }

    fun connect(it: WifiP2pDevice) {
        mConnectivityUtil.connect(it, object : ActionListener {
            override fun onSuccess() {
                Log.d(mTAG, "connect onSuccess")
            }

            override fun onFailure(reason: Int) {
                Log.d(mTAG, "connect onFailure: $reason")
            }
        })
    }


    fun cancelConnect(actionListener: ActionListener) {
        mConnectivityUtil.cancelConnect(actionListener)
    }

    fun disconnect() {
        mConnectivityUtil.disconnect(object : ActionListener {
            override fun onSuccess() {
                Log.d(mTAG, "disconnect onSuccess")
            }

            override fun onFailure(reason: Int) {
                Log.d(mTAG, "disconnect onFailure: $reason")
            }

        })
    }

    fun createGroup() {
        val wifiP2pConfig: WifiP2pConfig? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            WifiP2pConfig.Builder().setNetworkName("DIRECT-test").setPassphrase("12345678").build()
        } else {
            null
        }

        mConnectivityUtil.createGroup(wifiP2pConfig, object : ActionListener {
            override fun onSuccess() {
                Log.d(mTAG, "createGroup onSuccess")
                mConnectivityUtil.requestGroupInfo { group ->
                    Log.d(mTAG, "createGroup: $group")
                    Log.d(mTAG, "createGroup: ${group?.clientList}")
                    group?.let {
                        connectedWifiP2pGroup.postValue(it)
                    }
                }
            }

            override fun onFailure(reason: Int) {
                Log.d(mTAG, "createGroup onFailure: $reason")
            }
        })
    }


    fun unregisterReceiver() {
        mConnectivityUtil.unRegisterBroadcastReceiver()
    }

    fun connectWithPassword(ssid: String, password: String) {
        val wifiP2pConfig: WifiP2pConfig? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            WifiP2pConfig.Builder().setNetworkName("DIRECT-test").setPassphrase("12345678").build()
        } else {
            null
        }
        if (wifiP2pConfig != null) {
            mConnectivityUtil.connectWithConfig(wifiP2pConfig, object : ActionListener {
                override fun onSuccess() {
                    Log.d(mTAG, "connectWithPassword onSuccess")
                }

                override fun onFailure(reason: Int) {
                    Log.d(mTAG, "connectWithPassword onFailure: $reason")
                }
            })

        }
    }
}